/*
 * $HeadURL: $
 * $Id: $
 * Copyright (c) 2010 by Ericsson, all rights reserved.
 */

package com.younion.business.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.type.JavaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.younion.common.exception.BaseException;
import com.younion.dao.CardAgioDAO;
import com.younion.dao.CardLevelDAO;
import com.younion.util.json.JsonMapper;
import com.younion.vo.CardAgioVO;
import com.younion.vo.CardLevelVO;
import com.younion.vo.CustomerVO;
/**
*
* @author Joe Chen
* @version $Revision: $
*/
public class MemoryCacheManager {
    
    private static Logger logger = LoggerFactory.getLogger(MemoryCacheManager.class);

    private static final String CARD_LEVEL_KEY = "CARD_LEVEL_KEY#";
    private static final String CARD_AGIO_KEY = "CARD_AGIO_KEY#";
    
    private static final JsonMapper mapper = JsonMapper.buildNormalMapper();
    
    private CardLevelDAO cardLevelDAO;
    
    private CardAgioDAO cardAgioDAO;

    CacheLoader<String, String> loader = new CacheLoader<String, String>() {
        public String load(String key) {
            if (key.startsWith(CARD_LEVEL_KEY)) {
                return loadCardLevel(key);
            }else if(key.startsWith(CARD_AGIO_KEY)) {
                return loadCardAgio(key);
            } 
            return null;
        }
    };

    LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(loader);

    public List<CardLevelVO> getCardLevel(Integer customerId) {
        String json = "";
        List<CardLevelVO> cardLevelList = Lists.newArrayList();
        try {
            json = cache.get(CARD_LEVEL_KEY + String.valueOf(customerId));
        } catch (ExecutionException e) {
            logger.error("Loading card level from db failed", e.getMessage());
        }
        JavaType type = mapper.constructParametricType(ArrayList.class, CardLevelVO.class);
        cardLevelList = mapper.fromJson(json, type);
        return cardLevelList;
    }
    
    public List<CardAgioVO> getCardAgio(Integer customerId) {
        String json = "";
        List<CardAgioVO> cardLevelList = Lists.newArrayList();
        try {
            json = cache.get(CARD_AGIO_KEY + String.valueOf(customerId));
        } catch (ExecutionException e) {
            logger.error("Loading card agio from db failed", e.getMessage());
        }
        JavaType type = mapper.constructParametricType(ArrayList.class, CardAgioVO.class);
        cardLevelList = mapper.fromJson(json, type);
        return cardLevelList;
    }
    
    @SuppressWarnings("unchecked")
    @Transactional(readOnly = true)
    private String loadCardLevel(String key) {
        
        List<CardLevelVO> cardLevelList = Lists.newArrayList();
        Integer customerId = Integer.valueOf(StringUtils.split(key, "#")[1]);
        @SuppressWarnings("rawtypes")
        Map paramMap = new HashMap();
        CustomerVO cust = new CustomerVO();
        if(customerId > 0) cust.setId(customerId);
        paramMap.put("customerVO", cust);
        try {
            cardLevelList = (List<CardLevelVO>) cardLevelDAO.selectByMap(paramMap);
        } catch (BaseException e) {
        }
        return mapper.toJson(cardLevelList);
    }
    
    @SuppressWarnings("unchecked")
    @Transactional(readOnly = true)
    private String loadCardAgio(String key) {
        
        List<CardAgioVO> cardLevelList = Lists.newArrayList();
        Integer customerId = Integer.valueOf(StringUtils.split(key, "#")[1]);
        @SuppressWarnings("rawtypes")
        Map paramMap = new HashMap();
        CustomerVO cust = new CustomerVO();
        if(customerId > 0) cust.setId(customerId);
        paramMap.put("customerVO", cust);
        try {
            cardLevelList = (List<CardAgioVO>) cardAgioDAO.selectByMap(paramMap);
        } catch (BaseException e) {
        }
        return mapper.toJson(cardLevelList);
    }
    
    public void invalidateCardLevel(Integer customerId) {
        cache.invalidate(CARD_LEVEL_KEY + String.valueOf(customerId));
    }
    
    public void invalidateCardAgio(Integer customerId) {
        cache.invalidate(CARD_AGIO_KEY + String.valueOf(customerId));
    }

    public CardLevelDAO getCardLevelDAO() {
        return cardLevelDAO;
    }

    public void setCardLevelDAO(CardLevelDAO cardLevelDAO) {
        this.cardLevelDAO = cardLevelDAO;
    }

    public CardAgioDAO getCardAgioDAO() {
        return cardAgioDAO;
    }

    public void setCardAgioDAO(CardAgioDAO cardAgioDAO) {
        this.cardAgioDAO = cardAgioDAO;
    }
    
    
}
